home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1992 Eric R. Smith. All rights reserved.
- * Redistribution is permitted only if the distribution
- * is not for profit, and only if all documentation
- * (including, in particular, the file "copying")
- * is included in the distribution in unmodified form.
- * THIS PROGRAM COMES WITH ABSOLUTELY NO WARRANTY, NOT
- * EVEN THE IMPLIED WARRANTIES OF MERCHANTIBILITY OR
- * FITNESS FOR A PARTICULAR PURPOSE. USE AT YOUR OWN
- * RISK.
- */
- #include <stdlib.h>
- #include <gemfast.h>
- #include <aesbind.h>
- #include <vdibind.h>
- #include <osbind.h>
- #include <string.h>
- #include "xgem.h"
-
- #define WF_BEVENT 24
-
- #define IM_RESERVE 12345
- #define IM_RELEASE 12346
-
- /*
- * global variables
- */
-
- /* current top window */
- WINDOW *gl_topwin;
- extern WINDOW *focuswin;
-
- /* list of all windows in system */
- WINDOW *gl_winlist;
-
- /* do we want graf_{grow,shrink}box effects? */
- int win_flourishes = 1;
-
- /*
- * some dummy functions for windows
- */
-
- static void
- clear_win(v, x, y, w, h)
- WINDOW *v;
- int x,y,w,h;
- {
- int temp[4];
-
- vsf_color(vdi_handle, 0);
- temp[0] = x;
- temp[1] = y;
- temp[2] = x + w - 1;
- temp[3] = y + h - 1;
- v_bar(vdi_handle, temp);
- vsf_color(vdi_handle, 1);
- }
-
- static void
- top_win(w)
- WINDOW *w;
- {
- gl_topwin = w;
- wind_set(w->wi_handle, WF_TOP, 0, 0, 0, 0);
- }
-
- static void
- close_win(w)
- WINDOW *w;
- {
- destroy_window(w);
- }
-
- static void
- full_win(v)
- WINDOW *v;
- {
- int newx, newy, neww, newh;
-
- if (v->flags & WFULLED) {
- wind_get(v->wi_handle, WF_PREVXYWH, &newx, &newy, &neww,
- &newh);
- } else {
- wind_get(v->wi_handle, WF_FULLXYWH, &newx, &newy, &neww,
- &newh);
- }
-
- wind_set(v->wi_handle, WF_CURRXYWH, newx, newy, neww, newh);
- wind_get(v->wi_handle, WF_WORKXYWH, &v->wi_x, &v->wi_y, &v->wi_w,
- &v->wi_h);
-
- v->flags ^= WFULLED;
- }
-
- static void
- move_win(v, x, y, w, h)
- WINDOW *v;
- int x, y, w, h;
- {
- int fullx, fully, fullw, fullh;
-
- wind_get(v->wi_handle, WF_FULLXYWH, &fullx, &fully, &fullw, &fullh);
-
- if (w > fullw) w = fullw;
- if (h > fullh) h = fullh;
-
- if (w != fullw || h != fullh)
- v->flags &= ~WFULLED;
-
- wind_set(v->wi_handle, WF_CURRXYWH, x, y, w, h);
- wind_get(v->wi_handle, WF_WORKXYWH, &v->wi_x, &v->wi_y,
- &v->wi_w, &v->wi_h);
- }
-
- static void
- size_win(v, x, y, w, h)
- WINDOW *v;
- int x, y, w, h;
- {
- move_win(v, x, y, w, h);
- }
-
- static void
- noslid(w, m)
- WINDOW *w;
- int m;
- {
- }
-
- static int
- nokey(w, code)
- WINDOW *w;
- int code;
- {
- return 0;
- }
-
- static int
- nomouse(w, clicks, x, y, shift, mbuttons)
- WINDOW *w;
- int clicks, x, y, shift, mbuttons;
- {
- return 0;
- }
-
- static int
- iconmouse(v, clicks, x, y, shift, mbuttons)
- WINDOW *v;
- int clicks, x, y, shift, mbuttons;
- {
- int w, h;
-
- if (mbuttons) {
- /* wait for a little bit */
- evnt_timer(140L);
- graf_mkstate(&x, &y, &mbuttons, &shift);
- if (x < v->wi_x || x > v->wi_x + v->wi_w || y < v->wi_y ||
- y > v->wi_y + v->wi_w)
- return 1;
- if (mbuttons) { /* button still down */
- wind_update(BEG_MCTRL);
- graf_mouse(FLAT_HAND, 0L);
- wind_get(v->wi_handle, WF_CURRXYWH, &x, &y, &w, &h);
- graf_dragbox(w, h, x, y, xdesk, ydesk, wdesk, hdesk,
- &x, &y);
- graf_mouse(ARROW, 0L);
- wind_update(END_MCTRL);
- (*v->moved)(v, x, y, w, h);
- return 1;
- }
- }
- (*v->fulled)(v); /* un-iconify the window */
- return 1;
- }
-
- /* turn a window into an icon */
-
- static void
- uniconify_win(v)
- WINDOW *v;
- {
- static int mbuf[8];
- int newx, newy, neww, newh;
- int id = appl_find("ICONMGR ");
-
- if (!(v->flags & WICONIFIED)) return;
- if (id >= 0) {
- mbuf[0] = IM_RELEASE;
- mbuf[1] = gl_apid;
- mbuf[2] = 0;
- mbuf[3] = v->icon_slot;
- appl_write(id, 16, mbuf);
- }
- v->fulled = v->oldfulled;
- v->mouseinp = v->oldmouse;
- v->flags &= ~WICONIFIED;
-
- if (win_flourishes) {
- graf_growbox(v->wi_x, v->wi_y, v->wi_w, v->wi_h,
- v->prevx, v->prevy, v->prevw, v->prevh);
- }
- wind_calc(WC_BORDER, v->old_wkind, v->prevx, v->prevy, v->prevw,
- v->prevh, &newx, &newy, &neww, &newh);
- change_window_gadgets(v, v->old_wkind);
- (*v->sized)(v, newx, newy, neww, newh);
-
- /* button events should top the window */
- wind_set(v->wi_handle, WF_BEVENT, 0x0000, 0, 0, 0);
- (*v->topped)(v);
- }
-
- static void
- iconify_win(v, slot, x, y, w, h)
- WINDOW *v;
- int slot, x, y, w, h;
- {
- if (v->flags & WICONIFIED)
- return;
- v->flags &= ~WFULLED;
- v->flags |= WICONIFIED;
- v->oldfulled = v->fulled;
- v->oldmouse = v->mouseinp;
- v->icon_slot = slot;
- v->old_wkind = v->wi_kind;
-
- v->prevx = v->wi_x;
- v->prevy = v->wi_y;
- v->prevw = v->wi_w;
- v->prevh = v->wi_h;
- change_window_gadgets(v, 0);
- if (win_flourishes) {
- graf_shrinkbox(x, y, w, h, v->prevx, v->prevy, v->prevw,
- v->prevh);
- }
- (*v->sized)(v, x, y, w, h);
-
- /* we don't want the window topped inadvertently */
- wind_set(v->wi_handle, WF_BEVENT, 0x0001, 0, 0, 0);
- v->fulled = uniconify_win;
- v->mouseinp = iconmouse;
- new_topwin(1);
- }
-
- /*
- * Create a new window with title "title," initial/full size x, y, w, h,
- * and gadgets given by "kind." Returns a pointer to the new window,
- * or NULL if an error occurs. The window is not actually opened,
- * however.
- */
-
- /* used to "stagger" opening positions of windows */
- #define WOFF_INC gl_hbox
- #define WOFF_MAX 64
-
- static int winoff = 0;
-
- WINDOW *
- create_window(title, kind, wx, wy, ww, wh)
- const char *title;
- int kind, wx, wy, ww, wh;
- {
- WINDOW *v;
- int fullx, fully, fullw, fullh;
- int centerwin = 0;
-
- if (title) {
- title = strdup(title);
- }
-
- v = malloc(sizeof(WINDOW));
- if (!v) return v;
-
- v->wi_handle = -1; /* not open yet */
- v->wi_kind = kind;
-
- if (wx == 0 && wy == 0) centerwin = 1;
- if (wx < xdesk) wx = xdesk;
- if (wy < ydesk) wy = ydesk;
-
- /* calculate max. window size needed for a working area of ww x wh */
- wind_calc(WC_WORK, v->wi_kind, wx, wy, wdesk, hdesk,
- &v->wi_x, &v->wi_y, &v->wi_w, &v->wi_h);
- wind_calc(WC_BORDER, v->wi_kind, v->wi_x, v->wi_y, ww, wh,
- &fullx, &fully, &fullw, &fullh);
-
- if (fullw > wdesk)
- fullw = wdesk;
- if (fullh > hdesk)
- fullh = hdesk;
-
- if (centerwin) {
- fullx = xdesk;
- fully = ydesk;
- }
-
-
- fullx += winoff;
- fully += winoff;
- winoff += WOFF_INC;
- if (winoff > WOFF_MAX) {
- winoff = 0;
- }
-
- v->wi_title = (char *)title;
- v->wi_fullx = fullx;
- v->wi_fully = fully;
- v->wi_fullw = fullw;
- v->wi_fullh = fullh;
-
- wind_calc(WC_WORK, v->wi_kind, fullx, fully, fullw, fullh,
- &v->wi_x, &v->wi_y, &v->wi_w, &v->wi_h);
-
- v->wtype = GENERIC_WIN;
- v->extra = (void *)0;
- v->icon_slot = -1;
- v->flags = 0;
-
- v->draw = clear_win;
- v->topped = top_win;
- v->closed = close_win;
- v->fulled = full_win;
- v->sized = size_win;
- v->moved = move_win;
- v->arrowed = noslid;
- v->hslid = noslid;
- v->vslid = noslid;
- v->keyinp = nokey;
- v->mouseinp = nomouse;
- v->iconify = iconify_win;
- v->oldfulled = v->fulled;
- v->oldmouse = nomouse;
-
- v->menu = 0;
- v->infostr = 0;
-
- v->next = gl_winlist;
- gl_winlist = v;
- return v;
- }
-
- WINDOW *
- open_window(v)
- WINDOW *v;
- {
- int wx, wy, ww, wh;
-
- if (v->wi_handle >= 0) /* already open?? */
- return v;
-
- v->wi_handle = wind_create(v->wi_kind, v->wi_fullx, v->wi_fully,
- v->wi_fullw, v->wi_fullh);
-
- if (v->wi_handle < 0)
- return 0;
-
- wind_set(v->wi_handle, WF_BEVENT, 0x0000, 0, 0, 0);
- if (v->wi_kind & NAME) {
- if (v->wi_title)
- wind_set(v->wi_handle, WF_NAME, v->wi_title);
- else
- wind_set(v->wi_handle, WF_NAME, "Untitled");
- }
- if (v->wi_kind & INFO) {
- if (v->infostr) {
- wind_set(v->wi_handle, WF_INFO, v->infostr);
- } else {
- wind_set(v->wi_handle, WF_INFO, "");
- }
- }
-
- wind_calc(WC_BORDER, v->wi_kind, v->wi_x, v->wi_y, v->wi_w, v->wi_h,
- &wx, &wy, &ww, &wh);
-
- if (win_flourishes)
- graf_growbox(wx + ww/2, wy + wh/2, gl_wbox ,gl_hbox,
- wx, wy, ww, wh);
-
- wind_open(v->wi_handle, wx, wy, ww, wh);
-
- (*v->topped)(v);
- /* set scroll bars, etc. correctly */
- (*v->sized)(v, wx, wy, ww, wh);
- return v;
- }
-
- void
- close_window(v)
- WINDOW *v;
- {
- int i, dummy;
-
- if (v->wi_handle < 0) /* already closed? */
- return;
-
- wind_close(v->wi_handle);
- if (win_flourishes)
- graf_shrinkbox(v->wi_x + v->wi_w/2, v->wi_y + v->wi_h/2,
- gl_wbox, gl_hbox, v->wi_x, v->wi_y, v->wi_w, v->wi_h);
- wind_delete(v->wi_handle);
- v->wi_handle = -1;
-
- /* reset gl_topwin */
- gl_topwin = 0;
- wind_get(0, WF_TOP, &i, &dummy, &dummy, &dummy);
- for (v = gl_winlist; v; v = v->next) {
- if (v->wi_handle == i)
- break;
- }
- if (v && !(v->flags & WICONIFIED))
- (*v->topped)(v);
- }
-
- /*
- * destroy a window
- */
-
- void
- destroy_window(v)
- WINDOW *v;
- {
- WINDOW **ptr, *w;
- extern void unloadmenu();
-
- if (v->wi_handle >= 0) {
- close_window(v);
- }
-
- if (v->wi_title)
- free(v->wi_title);
-
- if (v->infostr)
- free(v->infostr);
-
- /* find v in the window list, and unlink it */
- ptr = &gl_winlist;
- w = *ptr;
- while (w) {
- if (w == v) {
- *ptr = v->next;
- break;
- }
- ptr = &w->next;
- w = *ptr;
- }
- /* maybe we should have an error here if v isn't found */
-
- free(v);
- }
-
- /*
- * redraw all parts of a window that lie within the rectangle
- * xc, yc, wc, hc
- */
-
- void
- redraw_window(v, xc, yc, wc, hc)
- WINDOW *v;
- int xc, yc, wc, hc;
- {
- GRECT t1, t2;
- int temp[4];
-
- wind_update(TRUE);
- hide_mouse();
- t2.g_x = xc;
- t2.g_y = yc;
- t2.g_w = wc;
- t2.g_h = hc;
- wind_get(v->wi_handle, WF_FIRSTXYWH,
- &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
-
- while (t1.g_w && t1.g_h) {
- if (rc_intersect(&t2, &t1)) {
- temp[0] = t1.g_x;
- temp[1] = t1.g_y;
- temp[2] = temp[0]+t1.g_w-1;
- temp[3] = temp[1]+t1.g_h-1;
- vs_clip(vdi_handle, 1, temp);
- (*v->draw)(v, t1.g_x, t1.g_y, t1.g_w, t1.g_h);
- }
- wind_get(v->wi_handle, WF_NEXTXYWH, &t1.g_x, &t1.g_y,
- &t1.g_w, &t1.g_h);
- }
- show_mouse();
- wind_update(FALSE);
- }
-
- /*
- * find a window
- */
-
- WINDOW *
- which_window(x)
- int x;
- {
- WINDOW *w;
-
- if (x < 0) return 0;
-
- for (w = gl_winlist; w; w = w->next)
- if (w->wi_handle == x)
- return w;
- return 0;
- }
-
- /*
- * handle an evnt_multi message dealing with windows
- */
-
- void
- handle_window(msgbuff)
- int *msgbuff;
- {
- WINDOW *v;
-
- v = which_window(msgbuff[3]);
- if (!v) { /* hmmm, not our window? */
- return;
- }
-
- switch(msgbuff[0]) {
- case WM_REDRAW:
- redraw_window(v, msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]);
- break;
- case WM_TOPPED:
- (*v->topped)(v);
- break;
- case WM_SIZED:
- (*v->sized)(v, msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]);
- break;
- case WM_MOVED:
- (*v->moved)(v, msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]);
- break;
- case WM_FULLED:
- (*v->fulled)(v);
- break;
- case WM_ARROWED:
- (*v->arrowed)(v, msgbuff[4]);
- break;
- case WM_HSLID:
- (*v->hslid)(v, msgbuff[4]);
- break;
- case WM_VSLID:
- (*v->vslid)(v, msgbuff[4]);
- break;
- case WM_CLOSED:
- (*v->closed)(v);
- break;
- }
- }
-
- int
- window_key(keycode, shift)
- int keycode, shift;
- {
- MENU *m;
- ENTRY *e;
- WINDOW *w;
-
- w = focuswin; /* set in evnt_loop */
-
- if (w) {
- /* first, check for window specific menu shortcut keys */
- for (m = w->menu; m; m = m->next) {
- for (e = m->contents; e; e = e->next) {
- if (e->keycode == keycode) {
- (*e->func)(e->arg);
- return 1;
- }
- }
- }
-
- /* otherwise, pass the key along to the general window handling thing */
- return (*w->keyinp)(w, keycode, shift);
- }
- else
- return 0;
- }
-
- int
- window_click(clicks, x, y, kshift, mbutton)
- int clicks, x, y, kshift, mbutton;
- {
- WINDOW *w;
-
- /* find the window that got clicked in (if any) */
- w = find_window(x, y);
- if (w) {
- return (*w->mouseinp)(w, clicks, x, y, kshift, mbutton);
- }
- return 0;
- }
-
- /*
- * close and delete all windows
- */
-
- void
- end_windows()
- {
- WINDOW *v;
-
- v = gl_winlist;
- while (v) {
- gl_winlist = v->next;
- if (v->wi_handle >= 0) {
- wind_close(v->wi_handle);
- wind_delete(v->wi_handle);
- }
- free(v);
- v = gl_winlist;
- }
- }
-
- /*
- * force a redraw of a whole window
- */
-
- void
- force_redraw(v)
- WINDOW *v;
- {
- redraw_window(v, v->wi_x, v->wi_y, v->wi_w, v->wi_h);
- if (v->wtype == TEXT_WIN)
- mark_clean(v->extra);
- }
-
- /*
- * find out which window lies under the point (x,y). Returns a pointer
- * to the window, or NULL
- */
-
- WINDOW *
- find_window(x, y)
- int x, y;
- {
- int wx, wy, ww, wh;
- WINDOW *w;
-
- wind_update(1); /* lock the screen -- we don't want it changing */
- for (w = gl_winlist; w; w = w->next) {
- if (w->wi_handle < 0) continue;
- wind_get(w->wi_handle, WF_FIRSTXYWH, &wx, &wy, &ww, &wh);
- while (ww && wh) {
- if (x >= wx && x <= wx + ww &&
- y >= wy && y <= wy + wh)
- goto found_window;
- wind_get(w->wi_handle, WF_NEXTXYWH, &wx, &wy, &ww, &wh);
- }
- }
- found_window:
- wind_update(0);
- return w; /* w will be null if no window found */
- }
-
- void
- change_window_gadgets(w, newkind)
- WINDOW *w;
- int newkind;
- {
- int reopen = 0;
- int nx, ny, nw, nh;
- int oldflourishes;
-
- if (newkind == w->wi_kind) return; /* no change */
-
- oldflourishes = win_flourishes;
- win_flourishes = 0;
-
- if (w->wi_handle >= 0) {
- wind_close(w->wi_handle);
- wind_delete(w->wi_handle);
- w->wi_handle = -1;
- reopen = 1;
- }
-
- wind_calc(WC_WORK, w->wi_kind, w->wi_fullx, w->wi_fully, w->wi_fullw,
- w->wi_fullh, &nx, &ny, &nw, &nh);
- wind_calc(WC_BORDER, newkind, nx, ny, nw, nh, &nx,
- &ny, &w->wi_fullw, &w->wi_fullh);
-
- if (w->wi_fullw > wdesk)
- w->wi_fullw = wdesk;
- if (w->wi_fullh > hdesk)
- w->wi_fullh = hdesk;
-
- if (w->wi_fullx < xdesk)
- w->wi_fullx = xdesk;
- if (w->wi_fully < ydesk)
- w->wi_fully = ydesk;
-
- wind_calc(WC_BORDER, w->wi_kind, w->wi_x, w->wi_y, w->wi_w, w->wi_h,
- &nx, &ny, &nw, &nh);
- if (nw > w->wi_fullw)
- nw = w->wi_fullw;
- if (nh > w->wi_fullh)
- nh = w->wi_fullh;
-
- wind_calc(WC_WORK, newkind, nx, ny, nw, nh, &w->wi_x, &w->wi_y,
- &w->wi_w, &w->wi_h);
-
- w->wi_kind = newkind;
-
- if (reopen) {
- open_window(w);
- }
- win_flourishes = oldflourishes;
- }
-
- /*
- * new_topwin: reset the top window so that it doesn't match the current
- * top window (if that's possible). If force == 0, then we allow the current
- * window to remain on top, otherwise we pretend that no window is on
- * top
- */
-
- void
- new_topwin(force)
- int force;
- {
- WINDOW *w;
- int mbuf[8];
-
- w = gl_topwin;
- if (!w) return;
- for(;;) {
- w = w->next;
- if (!w) w = gl_winlist;
- if (w->wi_handle >= 0 && !(w->flags & WICONIFIED)) break;
- if (w == gl_topwin) break;
- }
- if (w != gl_topwin) {
- mbuf[0] = WM_TOPPED;
- mbuf[1] = gl_apid;
- mbuf[2] = 0;
- mbuf[3] = w->wi_handle;
- mbuf[4] = mbuf[5] = mbuf[6] = mbuf[7] = 0;
- appl_write(gl_apid, 16, mbuf);
- } else if (force) {
- gl_topwin = 0;
- }
- }
-
- /* set a window title */
-
- void
- title_window(w, title)
- WINDOW *w; char *title;
- {
- if (w->wi_title)
- free(w->wi_title);
- w->wi_title = strdup(title);
- if (w->wi_handle >= 0 && (w->wi_kind & NAME)) {
- wind_set(w->wi_handle, WF_NAME, w->wi_title);
- }
- }
-